<!DOCTYPE html>
<html>

<head>
  <title>cannon.js - convex demo</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/style.css" type="text/css" />
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
  <script src="../../feng3d/out/feng3d.js"></script>
  <script src="../out/cannon.js"></script>
  <script src="../build/cannon.demo.js"></script>
  <script src="../libs/dat.gui.js"></script>
  <script src="../libs/Three.js"></script>
  <script src="../libs/TrackballControls.js"></script>
  <script src="../libs/Detector.js"></script>
  <script src="../libs/Stats.js"></script>
  <script src="../libs/smoothie.js"></script>
  <script>

    /**
     * Experiment for testing ConvexPolyhedrons.
     */
    var demo = new CANNON.Demo();

    function createTetra()
    {
      var verts = [new CANNON.Vector3(0, 0, 0),
      new CANNON.Vector3(2, 0, 0),
      new CANNON.Vector3(0, 2, 0),
      new CANNON.Vector3(0, 0, 2)];
      var offset = -0.35;
      for (var i = 0; i < verts.length; i++)
      {
        var v = verts[i];
        v.x += offset;
        v.y += offset;
        v.z += offset;
      }
      return new CANNON.ConvexPolyhedron(verts,
        [
          [0, 3, 2], // -x
          [0, 1, 3], // -y
          [0, 2, 1], // -z
          [1, 2, 3], // +xyz
        ]);
    }

    function createBoxPolyhedron(size)
    {
      size = size || 1;
      var box = new CANNON.Box(new CANNON.Vector3(size, size, size));
      return box.convexPolyhedronRepresentation;
    }

    // Various shapes
    demo.addScene("various", function ()
    {
      var world = setupWorld(demo);
      // ConvexPolyhedron box shape
      var size = 0.5;
      var convexShape = createBoxPolyhedron(size);
      var mass = 10;
      var boxbody = new CANNON.Body({ mass: mass });
      boxbody.addShape(convexShape);
      boxbody.position.set(1, 0, size + 1);
      world.addBody(boxbody);
      demo.addVisual(boxbody);

      // ConvexPolyhedron tetra shape
      var tetraShape = createTetra();
      var tetraBody = new CANNON.Body({ mass: mass });
      tetraBody.addShape(tetraShape);
      tetraBody.position.set(5, -3, size + 1);
      world.addBody(tetraBody);
      demo.addVisual(tetraBody);

      // ConvexPolyhedron cylinder shape
      var num = 20;
      var verts = [];
      var normals = [];
      var faces = [];
      var bottomface = [];
      var topface = [];
      var L = 2, R = 0.5;
      var cylinderShape = new CANNON.Cylinder(R, R, L, num);
      var cylinderBody = new CANNON.Body({ mass: mass });
      cylinderBody.addShape(cylinderShape);
      cylinderBody.position.set(0, 0, size * 4 + 1);
      cylinderBody.quaternion.fromAxisAngle(new CANNON.Vector3(0, 1, 0), Math.PI / 3);
      world.addBody(cylinderBody);
      demo.addVisual(cylinderBody);

    });


    // Box on box tilting over
    demo.addScene("convex on convex", function ()
    {
      var world = setupWorld(demo);
      // ConvexPolyhedron box shape
      var size = 2;
      var convexShape = createBoxPolyhedron(size);
      var mass = 10;
      var boxbody1 = new CANNON.Body({ mass: mass });
      boxbody1.addShape(convexShape);
      var boxbody2 = new CANNON.Body({ mass: mass });
      boxbody2.addShape(convexShape);
      boxbody1.position.set(0, 0, size + 1);
      boxbody2.position.set(1.5, 0, 4 * size + 1);
      world.addBody(boxbody1);
      world.addBody(boxbody2);
      demo.addVisual(boxbody1);
      demo.addVisual(boxbody2);
    });

    // Pile of boxes
    demo.addScene("convex wall", function ()
    {
      var world = setupWorld(demo);
      // ConvexPolyhedron box shape
      var size = 1;
      var convexShape = createBoxPolyhedron(size);
      var mass = 10;
      for (var i = 0; i < 3; i++)
      {
        for (var j = 0; j < 3; j++)
        {
          var boxbody = new CANNON.Body({ mass: mass });
          boxbody.addShape(convexShape);
          boxbody.position.set(2 * size * i + 0.01, 0, 2 * size * j + size * 1.2);
          world.addBody(boxbody);
          demo.addVisual(boxbody);
        }
      }
    });

    function setupWorld(demo)
    {
      var world = demo.getWorld();
      world.gravity.set(0, 0, -30);
      world.broadphase = new CANNON.NaiveBroadphase();
      world.solver.iterations = 10;

      world.defaultContactMaterial.contactEquationStiffness = 5e6;
      world.defaultContactMaterial.contactEquationRelaxation = 3;

      // ground plane
      var n = new CANNON.Vector3(0, 0, 1);
      n.normalize();
      var groundShape = new CANNON.Plane(n);
      var groundBody = new CANNON.Body({ mass: 0 });
      groundBody.addShape(groundShape);
      groundBody.position.set(-10, 0, 0);
      world.addBody(groundBody);
      demo.addVisual(groundBody);

      return world;
    };

    demo.start();

  </script>
</body>

</html>